package com.study.volatile关键字;

import java.util.concurrent.TimeUnit;

/**
 * volatile关键字演示
 */
public class VolatileDemo {

    private static boolean isOver = false;

    public static void main(String[] args) {
        // visibilityDemo();
        // volatileVisibilityDemo();
        // atomicDemo();

        new Thread(() -> {
            synchronized (VolatileDemo.class) {

            }
        }).start();


    }

    //可见性问题展示
    private static void visibilityDemo() {
        new Thread(() -> {
            while (!isOver) {
                try {
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        isOver = true;
        System.out.println("main---" + isOver);
    }

    //可见性
    private static void volatileVisibilityDemo() {
        System.out.println("可⻅性测试");
        //资源类
        MyData myData = new MyData();
        //启动⼀个线程操作共享数据
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "执⾏");
            try {
                //ThreadA先睡一会，确保主线程先拿到number的值
                TimeUnit.SECONDS.sleep(3);
                myData.setTo60();
                System.out.println(Thread.currentThread().getName() +
                        "更新number值:" + myData.number);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "ThreadA").start();
        while (myData.number == 0) {
            //main线程持有共享数据的拷⻉，⼀直为0，不会收到ThreadA修改number值的通知
            //注意加上下面这行代码，主线程将能走完，因为System.out.println方法有关键字sychronize，将会从主从中同步数据
            //System.out.println(myData.number);
        }
        System.out.println(Thread.currentThread().getName() + "main获取number值:" + myData.number);
    }

    //原子性
    private static void atomicDemo() {
        System.out.println("原⼦性测试");
        MyData myData = new MyData();
        for (int i = 1; i <= 20; i++) {
            new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    myData.addPlusPlus();
                    myData.addAtomic();
                }
            }, String.valueOf(i)).start();
        }
        while (Thread.activeCount() > 2) {
            Thread.yield();
        }
        System.out.println(Thread.currentThread().getName() + "int类型最终number值:" + myData.number);
        System.out.println(Thread.currentThread().getName() + "AtomicInteger类型最终number值: " + myData.atomicInteger);
    }
}

